import type { Mapless } from '..';
import type { IdHubType } from '../core/IdHub';
import IdHub from '../core/IdHub';
import { Manager } from '../core/manager';
import type { CurveOptions, ManagerOptions } from '../index.d';

type CurveIdHubType = IdHubType & {
  sourceId: string;
  layerId: string;
};

export default class CurveManager extends Manager<CurveIdHubType> {
  private curves: Record<string, GeoJSON.GeoJSON> = {};

  constructor(mapless: Mapless, options?: ManagerOptions) {
    super(mapless, options, 'curve');
    this.onInitialized();
  }

  override createIdHub(_idHub?: IdHubType): void {
    const newHub = new IdHub({
      layers: {
        layerId: 'dzmap-curve-layer',
      },
      sources: {
        sourceId: 'dzmap-curve-source',
      },
    }) as CurveIdHubType;
    super.createIdHub(newHub);
  }

  override initLayers() {
    if (!this.mapless) return;
    const sid = this.idHub?.sourceId;
    this.mapless.addEmptySource(sid);
    this.mapless.addLayer({
      id: this.idHub?.layerId,
      type: 'line',
      source: sid,
      paint: {
        'line-color': ['get', 'lineColor'],
        'line-width': ['get', 'lineWidth'],
      },
    });
  }

  drawCurve(id: string, options: CurveOptions) {
    const {
      coordinates,
      lineColor = 'rgba(255,0,0,0.1)',
      lineWidth = 0.3,
    } = options;
    const curve = {
      type: 'Feature' as const,
      geometry: {
        type: 'LineString' as const,
        coordinates,
      },
      properties: { id, lineColor, lineWidth },
    };
    this.curves[id] = curve;
    this.mapless?.setData(this.idHub?.sourceId, {
      type: 'FeatureCollection',
      features: Object.values(this.curves) as GeoJSON.Feature[],
    });
  }

  removeCurve(id: string) {
    if (!this.curves[id]) return;
    delete this.curves[id];
    this.mapless?.setData(this.idHub?.sourceId, {
      type: 'FeatureCollection',
      features: Object.values(this.curves) as GeoJSON.Feature[],
    });
  }

  removeAll() {
    this.mapless?.setEmptyData(this.idHub?.sourceId);
    this.curves = {};
  }

  override destroy() {
    super.destroy();
    this.curves = {};
  }
}

export const attachCurve = (mapless: Mapless | undefined, name?: string) =>
  mapless?.use(CurveManager, name);
export const getCurve = (mapless: Mapless | undefined, name?: string) =>
  mapless?.get(CurveManager, name);
export const detachCurve = (mapless: Mapless | undefined, name?: string) =>
  mapless?.unuse(CurveManager, name);
